<?php
abstract class Main_Db_Adapter_Abstract
{
	/**
	 * @var array
	 */
	protected $_options;
	
	/**
	 * @var int
	 */
	protected $_fetchMode;
	
	/**
     * Database connection
     * @var resource|null
     */
    protected $_connection = null;
	
    /**
     * @return bool
     */
    abstract protected function _connect();

    /**
     * @param string $sql
     * @return bool|resource
     */
    abstract public function query($sql);

    /**
     * @param string $sql
     * @param string $fetchMode
     * @return array
     */
 	abstract public function fetchAll($sql, $fetchMode = null);
 	
 	/**
 	 * @param string $sql
 	 * @param int $limit
 	 * @param int $offset
 	 * @param int $fetchMode
 	 * @return array
 	 */
 	abstract public function fetchAllLimited($sql, $limit, $offset, $fetchMode = null);
 	
 	/**
 	 * @param string $sql
 	 * @param int $fetchMode
 	 * @return array
 	 */
	abstract public function fetchRow($sql, $fetchMode = null);
	
	/**
	 * @param string $sql
	 * @param int $limit
	 * @param int $offset
	 * @param int  $fetchMode
	 * @return array
	 */
	abstract public function fetchRowLimited($sql, $limit, $offset, $fetchMode = null);
	
	/**
	 * @param string $sql
	 * @return string|int|null
	 */
	abstract public function fetchOne($sql);

	/**
	 * @param string $table
	 * @param array $data
	 * @return bool
	 */
	public function insert($table, $data)
	{
		if (!is_array($data)) {
			throw new Exception("Data must be array");
		}
		
		if (empty($data)) {
			throw new Exception("Data must be not empty");
		}
		
		$prefix = '';
		foreach ($data as $col => $val) {
			$cols .= $prefix . $col;
			$vals .= $prefix . $val;
			$prefix = ',';
		}
		
		$sql = "INSERT INTO {$table} ({$cols}) VALUES ({$vals})";
        return $this->query($sql);
	}
	
	/**
	 * @param string $table
	 * @param string $data
	 * @param string $where
	 * @return bool
	 */
	public function update($table, $data, $where='')
	{
		if (!is_array($data)) {
			throw new Exception("Data must be array");
		}
		
		if (empty($data)) {
			throw new Exception("Data must be not empty");
		}
		
		$setStr = '';
		$prefix = '';
		foreach ($data as $col => $val) {
			$setStr .= $prefix . "{$col}={$val}";
			$prefix = ',';	
		}
		
		$sql = "UPDATE {$table} SET $setStr " 
			 . ( !empty($where) ? " WHERE {$where}" : '');
			 
		return $this->query($sql);
	}
	
	/**
	 * @param string $table
	 * @param string $where
	 * @return bool
	 */
	public function delete($table, $where = '')
	{
		$sql = "DELETE FROM "
             . $table
             . (($where) ? " WHERE $where" : '');
		
		return $this->query($sql);
	}
	
	/**
	 * @param string|null $sequence
	 * @return int
	 */
	abstract public function lastInsertId($sequence = null);

	/**
	 * @param string $str
	 * @param bool $isQuote
	 * @return string
	 */
	abstract public function escape($str, $isQuote = false);
	
	/**
	 * @param array $config
	 * @return void
	 */
	public function __construct($config)
	{
		if (!is_array($config)) {
			throw new Exception('Конфигурационные параметры должны быть в виде массивом');
		}
		
		if (!isset($config['charset'])) {
            $config['charset'] = 'utf8';
        }
		
		$this->_checkRequiredOptions($config);
		
		$this->_options = $config;
	}
	
	/**
	 * @param array $config
	 * @return void
	 */
	protected function _checkRequiredOptions($config)
	{
		if (! array_key_exists('dbname', $config)) {
			throw new Exception("Configuration array must have a key for 'dbname' that names the database instance");	
		}
		
		if (! array_key_exists('password', $config)) {
            throw new Exception("Configuration array must have a key for 'password' for login credentials");
        }

        if (! array_key_exists('username', $config)) {
            throw new Exception("Configuration array must have a key for 'username' for login credentials");
        }
        
		if (! array_key_exists('host', $config)) {
            throw new Exception("Configuration array must have a key for 'host'");
        }
        
        if (! array_key_exists('port', $config)) {
            throw new Exception("Configuration array must have a key for 'port'");
        }
	}
	
	/**
	 * @return bool
	 */
    public function isConnected()
    {
        return ((bool) ($this->_connection !== null));
    }
    
    /**
     * @return void
     */
    public function closeConnection()
    {
        $this->_connection = null;
    }
	
	
	
	
}
